package com.alks.common.utils.export.service;

import cn.hutool.extra.spring.SpringUtil;
import com.alks.common.utils.MinIoUtil;
import com.alks.common.utils.export.dto.FileInfoDTO;
import com.alks.common.utils.export.dto.MockMultipartFile;
import com.alks.common.utils.export.service.impl.DefaultExportCallbackImpl;
import com.alks.common.utils.export.service.util.ExportTaskUtil;
import com.alks.entity.data.enums.ResultCodeEnum;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;

/**
 * @author: chen
 * @date: 2024/12/27
 * @description: 文件导出抽象类
 *      继承本类实现generateFile方法
 *      业务端需实现文件生成的逻辑，通过异步调用提交给服务器处理，接口返回{@link ResultCodeEnum#FILE_GENERATE}对应的编码
 */
@Slf4j
public abstract class FileExportTask {

    protected ExportCallback callback;

    final static protected String BUCKET = "tmp";

    public FileExportTask() {
        this.callback = new DefaultExportCallbackImpl();
    }

    public FileExportTask(ExportCallback callback) {
        this.callback = callback;
    }

    /**
     * 生成文件ID
     * @param createUser
     * @param originalFileName
     * @return
     */
    public static String startExport(String createUser, String originalFileName) {
        String taskFileName = ExportTaskUtil.startExportTask(createUser, originalFileName);
        FileInfoDTO fileInfo = new FileInfoDTO();
        fileInfo.setCreateBy(createUser);
        fileInfo.setOriginal(originalFileName);
        fileInfo.setBucket(BUCKET);
        fileInfo.setFileName(taskFileName);
        fileInfo.setCreateTime(LocalDateTime.now());
        IExportRecordService exportRecordService = SpringUtil.getBean(IExportRecordService.class);
        exportRecordService.record(fileInfo);
        return taskFileName;
    }

    /**
     * 执行导出
     * @param createUser    创建者 userId
     * @param taskFileName  文件名称
     */
    public void export(String createUser, String taskFileName) {
        IExportRecordService exportRecordService = SpringUtil.getBean(IExportRecordService.class);
        FileInfoDTO fileInfo = null;
        try {
            // 初始化
            fileInfo = init(createUser, taskFileName);

            // 文件生成
            MockMultipartFile file = generateFile(fileInfo.getOriginal());
            fileInfo.setFileSize(file.getSize());

            // 文件上传
            uploadFile(file, fileInfo.getFileName());
            fileInfo.setGenerationTime(LocalDateTime.now());

            // 完成后回调
            callback.onComplete(fileInfo);

            // 更新状态
            exportRecordService.updateRecord(fileInfo, true);

        } catch (Exception e) {
            callback.onError(e);
            if (fileInfo != null) {
                exportRecordService.updateRecord(fileInfo, false);
            }
        } finally {
            ExportTaskUtil.removeExportTask(createUser, taskFileName);
        }
    }

    /**
     * 初始化导出文件信息
     * @param createUser
     * @param taskFileName
     * @return
     */
    private FileInfoDTO init(String createUser, String taskFileName) {
        String originalName = ExportTaskUtil.getOriginalName(createUser, taskFileName);
        FileInfoDTO fileInfo = new FileInfoDTO();
        fileInfo.setCreateBy(createUser);
        fileInfo.setOriginal(originalName);
        fileInfo.setBucket(BUCKET);
        fileInfo.setFileName(taskFileName);
        return fileInfo;
    }

    protected abstract MockMultipartFile generateFile(String fileName) throws Exception;       // 生成文件的逻辑

    private void uploadFile(MockMultipartFile file, String fileName) {
        log.debug("开始上传文件");
        MinIoUtil minIoUtil = SpringUtil.getBean(MinIoUtil.class);
        if(minIoUtil.upload(file, BUCKET, fileName)) {
            callback.onProgressUpdate(1);
            log.debug("文件上传成功");
        } else {
            log.warn("文件上传失败");
        }
    }
}
